//: Playground - noun: a place where people can play

import UIKit
//: # swfit 读书笔记

//: ## 访问控制

//: ### 访问控制关键字
//: open > public > interal > fileprivate > private

//:internal(可以不写)
//: * swfit 默认创建的代码实例(类、属性、方法就)是这个级别,internal 创建的类和属性在本框架(SDK、app)的模块内随意访问，但是不能在其他的框架内访问
//: * 如果SDK或者框架暴露 api 不能是 internal 级别的， 应该是 public、open

//:open
//: * 可以被任何人使用，包括 override 和继承。

//:public
//: * 在本模块内和internal级别是一样的(继承、重写),但是在其他模块中可以被引用但是不能继承和重写。 internal 不可以被其他模块引用，但是 public 可以

//:fileprivate
//: * 修饰的方法和属性只能在当前的文件中使用，可以访问父类的fileprivate 修饰的属性和方法， 在extension 文件中可以访问当前文件fileprivate 修饰的属性和方法
class fileprivateClass{
    fileprivate let fileprivatePro:Int = 40
}

extension fileprivateClass{
    func fileprivateNSlog() {
        print("\(fileprivatePro)")
    }
}
fileprivateClass().fileprivateNSlog()

class fileprivateClassTwo:fileprivateClass{
    override convenience init() {
        self.init()
        //: 可以访问
        print("fileprivateClassTwo - \(fileprivatePro)")
    }
}

//:private
//: * 修饰的方法和属性只能在当前类使用，无法访问父类的private 修饰的属性和方法（swfit 4.0 中在extension 能访问 ）
class privateClass{
    private let privatePro:Int = 30
}

extension privateClass{
    func privateNSlog() {
        print(" privateClass - \(privatePro)")
    }
}
privateClass().privateNSlog()

class privateClassTwo:privateClass{
    override init() {
        //: 虽然 privateClassTwo继承privateClass 但是 它不能访问父类(privateClass)的 private 修饰的属性和方法，但是 fileprivate是可以的
//        print("\(privatePro)")
    }
}

//: ### 类
//: * 如果 Class的访问级别是 private 或者 filterprivate 则 方法属性是对应的级别
//: * 如果 Class的访问级别是 open 或者 public 则 方法和属性的默认级别是 internal

//: ### 元组类型
//: * 元组的访问级别将由元组中访问级别最严格的类型来决定

//: ### 函数类型
//: * 函数的访问级别根据访问级别最严格的参数类型或返回类型的访问级别来决定

//: ### 枚举类型
//: * 枚举成员的访问级别和该枚举类型相同，你不能为枚举成员单独指定不同的访问级别
//: * 枚举定义中的任何原始值或关联值的类型的访问级别至少不能低于枚举类型的访问级别

public enum CompassPoint {
    case North
    case South
    case East
    case West
}

//: ### 子类
//: * 子类的访问级别不得高于父类的访问级别。例如，父类的访问级别是 internal，子类的访问级别就不能是 public

class zzpClass{
    internal var zzpPro:Int = 9
}

//: ### 常量、变量、属性、下标
//: * 它们不能拥有比他们类型更高的级别。
//: * Getter 和 Setter
//: * 常量、变量、属性、下标 的 Getrer 和 Setter 默认是是和它们的属性相同的，但是 Setter 的方法可以比Getter方法的级别底。
//: * 比如 fileprivate(set)，private(set) 或 internal(set) 为它们的写入权限指定更低的访问级别

class PropertiesClass{
    //: 这两个属性都是 对内读写 对外只读的  internal 可以隐藏
    private(set) var someNum:Int = 23
    
    internal private(set) var someMoreNum:Int = 24
}

//: ### 构造器
//: * 自定义构造器 可以低于或者等于所属类型的级别。
//: * 必须构造器 访问级别必须和所属的类型一致。
//: * 默认构造器 他默认是和所属类型一样的，但是如果 类型 是 public 级别 默认构造器是 internal， 如果想要一个 public 级别的只能自己实现
//: * 结构体默认的成员逐一构造器  默认是 internal , 其他情况是和属性一样， 如果想要一个 public 级别的只能自己实现

//: ### 协议
//: * 协议创建是如果指定了级别，协议要求的方法和属性就和协议是一个级别。
//: * 协议继承： 最高级别是继承的协议的级别。
//: * 协议的一致性： 类型可以采纳比自己访问级别底的协议、类型和协议访问级别是取最低的、类型实现协议的要求不能低于写的访问级别。

//: ### 扩展
//: * 对类、结构体、枚举、的扩展默认是和原始类相同的级别。但是我们可以单独指定 extension 特定级别 (private extension)
//: * 对协议就不能显示的指定协议的控制级别，它是默认的访问级别不能更改。

//: ### 泛型
//: * 泛型函数或者泛型类型访问级别，取决于自身和类型参数的类型访问级别中最低的。


